home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / DirectX SDK / DXSDK / samples / Multimedia / DirectShow_WinXP / VMR / Cube / compositor.cpp < prev    next >
C/C++ Source or Header  |  2001-10-08  |  22KB  |  626 lines

  1. //------------------------------------------------------------------------------
  2. // File: compositor.cpp
  3. //
  4. // Desc: DirectShow sample code - VMR-based Cube video player
  5. //
  6. // Copyright (c) 1994 - 2001, Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8.  
  9. #include <streams.h>
  10. #include <dvdmedia.h>
  11. #include <mmreg.h>
  12. #include <commctrl.h>
  13.  
  14. #include "project.h"
  15. #include <stdarg.h>
  16. #include <stdio.h>
  17.  
  18.  
  19. /*****************************Private*Routine******************************\
  20. * MakeD3DVector
  21. *
  22. \**************************************************************************/
  23. D3DVECTOR
  24. MakeD3DVector( float x, float y, float z )
  25. {
  26.     D3DVECTOR ret;
  27.     ret.x = x;
  28.     ret.y = y;
  29.     ret.z = z;
  30.     return ret;
  31. }
  32.  
  33. /*****************************Private*Routine******************************\
  34. * MakeD3DVertex
  35. *
  36. \**************************************************************************/
  37. D3DVERTEX
  38. MakeD3DVertex( const D3DVECTOR& p, const D3DVECTOR& n, float tu, float tv )
  39. {
  40.     D3DVERTEX ret;
  41.     ret.x = p.x;  ret.y = p.y;  ret.z = p.z;
  42.     ret.nx = n.x; ret.ny = n.y; ret.nz = n.z;
  43.     ret.tu = tu; ret.tv = tv;
  44.     return ret;
  45.  
  46. }
  47.  
  48. /*****************************Private*Routine******************************\
  49. * Name: MatrixMultiply()
  50. * Desc: Multiplies matrix B onto matrix A, as in: [Q] = [B] * [A].
  51. \**************************************************************************/
  52. VOID MatrixMultiply( D3DMATRIX& q, D3DMATRIX& a, D3DMATRIX& b )
  53. {
  54.     FLOAT* pA = (FLOAT*)&a;
  55.     FLOAT* pB = (FLOAT*)&b;
  56.     FLOAT  pM[16];
  57.  
  58.     ZeroMemory( pM, sizeof(D3DMATRIX) );
  59.  
  60.     for( DWORD i=0; i<4; i++ ) 
  61.         for( DWORD j=0; j<4; j++ ) 
  62.             for( DWORD k=0; k<4; k++ ) 
  63.                 pM[4*i+j] += pA[4*k+j] * pB[4*i+k];
  64.  
  65.     memcpy( &q, pM, sizeof(D3DMATRIX) );
  66. }
  67.  
  68. /*****************************Private*Routine******************************\
  69. * CreateCube()
  70. *
  71. * Sets up the vertices for a cube. Don't forget to set the texture
  72. * coordinates for each vertex.
  73. *
  74. \**************************************************************************/
  75. VOID
  76. CreateCube(
  77.     D3DVERTEX* pVertices,
  78.     StreamSize * pSize
  79.     )
  80. {
  81.     // Define the normals for the cube
  82.     D3DVECTOR n0 = MakeD3DVector( 0.0f, 0.0f, 1.0f ); // Front face
  83.     D3DVECTOR n4 = MakeD3DVector( 1.0f, 0.0f, 0.0f ); // Right face
  84.     D3DVECTOR n1 = MakeD3DVector( 0.0f, 0.0f, 1.0f ); // Back face
  85.     D3DVECTOR n5 = MakeD3DVector(-1.0f, 0.0f, 0.0f ); // Left face
  86.     D3DVECTOR n2 = MakeD3DVector( 0.0f, 1.0f, 0.0f ); // Top face
  87.     D3DVECTOR n3 = MakeD3DVector( 0.0f,-1.0f, 0.0f ); // Bottom face
  88.  
  89.     // Front face
  90.     *pVertices++ = MakeD3DVertex( MakeD3DVector(-1.0f, 1.0f,-1.0f), n0, 0.0f, 0.0f );
  91.     *pVertices++ = MakeD3DVertex( MakeD3DVector( 1.0f, 1.0f,-1.0f), n0, pSize[0].cx  , 0.0f );
  92.     *pVertices++ = MakeD3DVertex( MakeD3DVector(-1.0f,-1.0f,-1.0f), n0, 0.0f, pSize[0].cy   );
  93.     *pVertices++ = MakeD3DVertex( MakeD3DVector( 1.0f,-1.0f,-1.0f), n0, pSize[0].cx  , pSize[0].cy   );
  94.  
  95.      // Right face
  96.     *pVertices++ = MakeD3DVertex( MakeD3DVector( 1.0f, 1.0f,-1.0f), n4, 0.0f, 0.0f );
  97.     *pVertices++ = MakeD3DVertex( MakeD3DVector( 1.0f, 1.0f, 1.0f), n4, pSize[1].cx  , 0.0f );
  98.     *pVertices++ = MakeD3DVertex( MakeD3DVector( 1.0f,-1.0f,-1.0f), n4, 0.0f, pSize[1].cy   );
  99.     *pVertices++ = MakeD3DVertex( MakeD3DVector( 1.0f,-1.0f, 1.0f), n4, pSize[1].cx  , pSize[1].cy   );
  100.  
  101.     // Top face
  102.     *pVertices++ = MakeD3DVertex( MakeD3DVector(-1.0f, 1.0f, 1.0f), n2, 0.0f, 0.0f );
  103.     *pVertices++ = MakeD3DVertex( MakeD3DVector( 1.0f, 1.0f, 1.0f), n2, pSize[2].cx  , 0.0f );
  104.     *pVertices++ = MakeD3DVertex( MakeD3DVector(-1.0f, 1.0f,-1.0f), n2, 0.0f, pSize[2].cy   );
  105.     *pVertices++ = MakeD3DVertex( MakeD3DVector( 1.0f, 1.0f,-1.0f), n2, pSize[2].cx  , pSize[2].cy   );
  106.  
  107.     // Back face
  108.     *pVertices++ = MakeD3DVertex( MakeD3DVector(-1.0f, 1.0f, 1.0f), n1, pSize[0].cx  , 0.0f );
  109.     *pVertices++ = MakeD3DVertex( MakeD3DVector(-1.0f,-1.0f, 1.0f), n1, pSize[0].cx  , pSize[0].cy   );
  110.     *pVertices++ = MakeD3DVertex( MakeD3DVector( 1.0f, 1.0f, 1.0f), n1, 0.0f, 0.0f );
  111.     *pVertices++ = MakeD3DVertex( MakeD3DVector( 1.0f,-1.0f, 1.0f), n1, 0.0f, pSize[0].cy   );
  112.  
  113.     // Left face
  114.     *pVertices++ = MakeD3DVertex( MakeD3DVector(-1.0f, 1.0f,-1.0f), n5, pSize[1].cx  , 0.0f );
  115.     *pVertices++ = MakeD3DVertex( MakeD3DVector(-1.0f,-1.0f,-1.0f), n5, pSize[1].cx  , pSize[1].cy   );
  116.     *pVertices++ = MakeD3DVertex( MakeD3DVector(-1.0f, 1.0f, 1.0f), n5, 0.0f, 0.0f );
  117.     *pVertices++ = MakeD3DVertex( MakeD3DVector(-1.0f,-1.0f, 1.0f), n5, 0.0f, pSize[1].cy   );
  118.  
  119.     // Bottom face
  120.     *pVertices++ = MakeD3DVertex( MakeD3DVector(-1.0f,-1.0f, 1.0f), n3, 0.0f, 0.0f );
  121.     *pVertices++ = MakeD3DVertex( MakeD3DVector(-1.0f,-1.0f,-1.0f), n3, 0.0f, pSize[2].cy   );
  122.     *pVertices++ = MakeD3DVertex( MakeD3DVector( 1.0f,-1.0f, 1.0f), n3, pSize[2].cx  , 0.0f );
  123.     *pVertices++ = MakeD3DVertex( MakeD3DVector( 1.0f,-1.0f,-1.0f), n3, pSize[2].cx  , pSize[2].cy   );
  124. }
  125.  
  126. /*****************************Private*Routine******************************\
  127. * FrameMove
  128. *
  129. * Called once per frame, the call is used for animating the scene. The
  130. * device is used for changing various render states, and the timekey is
  131. * used for timing of the dynamics of the scene.
  132. *
  133. \**************************************************************************/
  134. HRESULT
  135. CMpegMovie::FrameMove(
  136.     LPDIRECT3DDEVICE7 pd3dDevice,
  137.     FLOAT fTimeKey
  138.     )
  139. {
  140.     HRESULT hr = S_OK;
  141.  
  142.     __try {
  143.  
  144.         // Set the view matrix so that the camera is backed out along the z-axis,
  145.         // and looks down on the cube (rotating along the x-axis by -0.5 radians).
  146.         D3DMATRIX matView;
  147.         ZeroMemory(&matView, sizeof(D3DMATRIX));
  148.  
  149.         matView._11 = 1.0f;
  150.         matView._22 =  (FLOAT)cos(-0.5f);
  151.         matView._23 =  (FLOAT)sin(-0.5f);
  152.         matView._32 = -(FLOAT)sin(-0.5f);
  153.         matView._33 =  (FLOAT)cos(-0.5f);
  154.         matView._43 = 5.0f;
  155.         matView._44 = 1.0f;
  156.         CHECK_HR(hr = pd3dDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &matView));
  157.  
  158.         // Set the world matrix to rotate along the y-axis, in sync with the timekey
  159.         D3DMATRIX matRotate, matRotate2, matWorld;
  160.         ZeroMemory(&matRotate, sizeof(D3DMATRIX));
  161.         ZeroMemory(&matRotate2, sizeof(D3DMATRIX));
  162.         ZeroMemory(&matWorld, sizeof(D3DMATRIX));
  163.  
  164.         // rotate along y axis
  165.         matRotate._11 =  (FLOAT)cos(fTimeKey);
  166.         matRotate._13 =  (FLOAT)sin(fTimeKey);
  167.         matRotate._22 =  1.0f;
  168.         matRotate._31 = -(FLOAT)sin(fTimeKey);
  169.         matRotate._33 =  (FLOAT)cos(fTimeKey);
  170.         matRotate._44 =  1.0f;
  171.  
  172.         // rotate along z axis
  173.         matRotate2._11 = (FLOAT)cos(fTimeKey);
  174.         matRotate2._12 = (FLOAT)sin(fTimeKey);
  175.         matRotate2._21 = -(FLOAT)sin(fTimeKey);
  176.         matRotate2._22 = (FLOAT)cos(fTimeKey);
  177.         matRotate2._33 =  1.0f;
  178.         matRotate2._44 =  1.0f;
  179.  
  180.         MatrixMultiply(matWorld, matRotate, matRotate2);
  181.         CHECK_HR(hr = pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matWorld));
  182.     }
  183.     __finally {}
  184.  
  185.     return hr;
  186. }
  187.  
  188. /******************************Public*Routine******************************\
  189. * GetSourceRectFromMediaType
  190. *
  191. \**************************************************************************/
  192. RECT
  193. GetSourceRectFromMediaType(
  194.     const AM_MEDIA_TYPE *pMediaType
  195.     )
  196. {
  197.     RECT rRect = {0,0,0,0};
  198.     if (!pMediaType)
  199.     {
  200.         DbgLog((LOG_ERROR, 1, TEXT("pMediaType is NULL")));
  201.         return rRect;
  202.     }
  203.  
  204.     if (!(pMediaType->pbFormat))
  205.     {
  206.         return rRect;
  207.     }
  208.  
  209.     if ((pMediaType->formattype == FORMAT_VideoInfo) &&
  210.         (pMediaType->cbFormat >= sizeof(VIDEOINFOHEADER)))
  211.     {
  212.         rRect = (((VIDEOINFOHEADER*)(pMediaType->pbFormat))->rcSource);
  213.     }
  214.     else if ((pMediaType->formattype == FORMAT_VideoInfo2) &&
  215.              (pMediaType->cbFormat >= sizeof(VIDEOINFOHEADER2)))
  216.     {
  217.         rRect = (((VIDEOINFOHEADER2*)(pMediaType->pbFormat))->rcSource);
  218.     }
  219.  
  220.     // DShow filters have the habit of sometimes not setting the src and dst
  221.     // rectangles, in this case we should imply that the these rectangles
  222.     // should be the same width and height as the bitmap in the media format.
  223.     if (IsRectEmpty(&rRect)) 
  224.     {
  225.         LPBITMAPINFOHEADER lpbi = GetbmiHeader(pMediaType);
  226.  
  227.         if (lpbi) 
  228.         {
  229.             SetRect(&rRect, 0, 0, abs(lpbi->biWidth), abs(lpbi->biHeight));
  230.         }
  231.     }
  232.  
  233.     return rRect;
  234. }
  235.  
  236. /*****************************Private*Routine******************************\
  237. * GetbmiHeader
  238. *
  239. * Returns the bitmap info header associated with the specified CMediaType.
  240. * Returns NULL if the CMediaType is not either of FORMAT_VideoInfo or
  241. * FORMAT_VideoInfo2.
  242. *
  243. \**************************************************************************/
  244. LPBITMAPINFOHEADER
  245. GetbmiHeader(
  246.     const AM_MEDIA_TYPE *pMediaType
  247.     )
  248. {
  249.     AMTRACE((TEXT("GetbmiHeader")));
  250.  
  251.     if (!pMediaType)
  252.     {
  253.         DbgLog((LOG_ERROR, 1, TEXT("pMediaType is NULL")));
  254.         return NULL;
  255.     }
  256.  
  257.     if (!(pMediaType->pbFormat))
  258.     {
  259.         DbgLog((LOG_ERROR, 1, TEXT("pMediaType->pbFormat is NULL")));
  260.         return NULL;
  261.     }
  262.  
  263.     LPBITMAPINFOHEADER lpHeader = NULL;
  264.     if ((pMediaType->formattype == FORMAT_VideoInfo) &&
  265.         (pMediaType->cbFormat >= sizeof(VIDEOINFOHEADER)))
  266.     {
  267.         lpHeader = &(((VIDEOINFOHEADER*)(pMediaType->pbFormat))->bmiHeader);
  268.     }
  269.     else if ((pMediaType->formattype == FORMAT_VideoInfo2) &&
  270.              (pMediaType->cbFormat >= sizeof(VIDEOINFOHEADER2)))
  271.     {
  272.         lpHeader = &(((VIDEOINFOHEADER2*)(pMediaType->pbFormat))->bmiHeader);
  273.     }
  274.  
  275.     return lpHeader;
  276. }
  277.  
  278. /*****************************Private*Routine******************************\
  279. * AllocateTextureMirror
  280. *
  281. \**************************************************************************/
  282.  
  283. // global data structures and static helper function for AllocateTextureMirror
  284. const DDPIXELFORMAT g_rgTextMirFormats[] = {
  285.     { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 32, 0xff0000, 0xff00,  0xff, 0xff<<24ul},
  286.     { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 24, 0xff0000, 0xff00,  0xff, 0       },
  287.     { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x1f<<11, 0x3f<<5, 0x1f, 0       },
  288.     { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x1f<<10, 0x1f<<5, 0x1f, 0       }
  289. };
  290.  
  291. const UINT g_cTextMirFormats = sizeof(g_rgTextMirFormats)/sizeof(DDPIXELFORMAT);
  292.  
  293. static UINT
  294. NextPow2( UINT i )
  295. {
  296.     UINT ret = 1;
  297.     while ( ret < i )
  298.     {
  299.         ret <<= 1;
  300.     }
  301.     return ret;
  302. }
  303.  
  304.  
  305. /*****************************Private*Routine******************************\
  306. * AllocateTextureMirror
  307. *
  308. \**************************************************************************/
  309. HRESULT
  310. CMpegMovie::AllocateTextureMirror(
  311.     LPDIRECTDRAWSURFACE7 pddsVideo,
  312.     DWORD* lpdwWidth,
  313.     DWORD* lpdwHeight, 
  314.     bool bNonPow2Cond
  315.     )
  316. {
  317.     HRESULT hr = E_UNEXPECTED;
  318.     DDSURFACEDESC2 ddsd = {sizeof(ddsd)};
  319.  
  320.     __try {
  321.  
  322.         LPDIRECTDRAW7 pDD;
  323.  
  324.         CHECK_HR(pddsVideo->GetDDInterface((LPVOID*)&pDD));
  325.  
  326.         if (m_pDDSTextureMirror) {
  327.  
  328.             CHECK_HR(hr = m_pDDSTextureMirror->GetSurfaceDesc(&ddsd));
  329.  
  330.             // early out if mirror already exists and is large enough to accommodate pDDS
  331.             if (ddsd.dwWidth >= *lpdwWidth && ddsd.dwHeight >= *lpdwHeight) {
  332.                 *lpdwWidth = ddsd.dwWidth;
  333.                 *lpdwHeight = ddsd.dwHeight;
  334.                 return S_OK;
  335.             }
  336.  
  337.             *lpdwWidth = max(ddsd.dwWidth, *lpdwWidth);
  338.             *lpdwHeight = max(ddsd.dwHeight, *lpdwHeight);
  339.         }
  340.  
  341.         RELEASE(m_pDDSTextureMirror);
  342.  
  343.         // bump dimensions out to next power of 2
  344.         // if the 3D hardware needs it that way
  345.  
  346.         if (!bNonPow2Cond) {
  347.             *lpdwWidth = NextPow2(*lpdwWidth);
  348.             *lpdwHeight = NextPow2(*lpdwHeight);
  349.         }
  350.  
  351.         DDSURFACEDESC2 ddsd = {sizeof(ddsd)};
  352.         ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
  353.         ddsd.dwWidth = *lpdwWidth;
  354.         ddsd.dwHeight = *lpdwHeight;
  355.         ddsd.ddsCaps.dwCaps |= DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
  356.  
  357.         // loop over texture formats and return as soon as CreateSurface succeeds
  358.         for (UINT i = 0; i < g_cTextMirFormats; i++) {
  359.  
  360.             // create texture mirror
  361.             ddsd.ddpfPixelFormat = g_rgTextMirFormats[i];
  362.             hr = pDD->CreateSurface(&ddsd, &m_pDDSTextureMirror, NULL);
  363.             if (SUCCEEDED(hr))
  364.                 break;
  365.         }
  366.         RELEASE(pDD);
  367.     }
  368.     __finally {}
  369.  
  370.     return hr;
  371. }
  372.  
  373.  
  374. /*****************************Private*Routine******************************\
  375. * InitCompositionTarget
  376. *
  377. \**************************************************************************/
  378. STDMETHODIMP
  379. CMpegMovie::InitCompositionTarget(
  380.     IUnknown* lpUnk,
  381.     LPDIRECTDRAWSURFACE7 pddsRenderTarget
  382.     )
  383. {
  384.     HRESULT hr = S_OK;
  385.  
  386.     __try {
  387.  
  388.         LPDIRECT3DDEVICE7 pd3dDevice = (LPDIRECT3DDEVICE7)lpUnk;
  389.         DDSURFACEDESC2 ddsd = {sizeof(DDSURFACEDESC2)};
  390.  
  391.         CHECK_HR(hr = pddsRenderTarget->GetSurfaceDesc(&ddsd));
  392.  
  393.         D3DVIEWPORT7 vp = { 0, 0, ddsd.dwWidth, ddsd.dwHeight, 0.0f, 1.0f };
  394.         CHECK_HR(hr = pd3dDevice->SetViewport(&vp));
  395.  
  396.         //
  397.         // Remind the CompositeImage (see below) to init the cube vertices.
  398.         // We can't do it here because we don't know the size of the movie
  399.         // being played yet.
  400.         //
  401.         m_bInitCube = true;
  402.  
  403.         // For simplicity, just use ambient lighting and a white material
  404.         D3DMATERIAL7 mtrl;
  405.         ZeroMemory(&mtrl, sizeof(mtrl));
  406.         mtrl.diffuse.r = mtrl.diffuse.g = mtrl.diffuse.b = 1.0f;
  407.         mtrl.ambient.r = mtrl.ambient.g = mtrl.ambient.b = 1.0f;
  408.         CHECK_HR(hr = pd3dDevice->SetMaterial(&mtrl));
  409.         CHECK_HR(hr = pd3dDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff));
  410.  
  411.         // Set the projection matrix. Note that the view and world matrices are
  412.         // set in the App_FrameMove() function, so they can be animated each
  413.         // frame.
  414.         D3DMATRIX matProj;
  415.         ZeroMemory(&matProj, sizeof(D3DMATRIX));
  416.         matProj._11 =  2.0f;
  417.         matProj._22 =  2.0f;
  418.         matProj._33 =  1.0f;
  419.         matProj._34 =  1.0f;
  420.         matProj._43 = -1.0f;
  421.         CHECK_HR(hr = pd3dDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &matProj));
  422.     }
  423.     __finally {
  424.     };
  425.  
  426.     return hr;
  427. }
  428.  
  429. /*****************************Private*Routine******************************\
  430. * CompositeImage
  431. *
  432. \**************************************************************************/
  433. STDMETHODIMP
  434. CMpegMovie::CompositeImage(
  435.     IUnknown* lpUnk,
  436.     LPDIRECTDRAWSURFACE7 pddsRenderTarget,
  437.     AM_MEDIA_TYPE* pmtRenderTarget,
  438.     REFERENCE_TIME rtStart,
  439.     REFERENCE_TIME rtEnd,
  440.     DWORD dwMapped,
  441.     VMRVIDEOSTREAMINFO* pStrmInfo,
  442.     UINT cStreams
  443.     )
  444. {
  445.     LPDIRECT3DDEVICE7 pd3dDevice = (LPDIRECT3DDEVICE7)lpUnk;
  446.     HRESULT hr = S_OK;
  447.     bool bInScene = false;
  448.  
  449.     __try 
  450.     {
  451.         LPDIRECTDRAWSURFACE7 pDDS;
  452.  
  453.         //
  454.         // First time thru init the Cube compositor
  455.         //
  456.         if (m_bInitCube) 
  457.         { 
  458.             // if the dimensions are not 0, one of the surfaces is not a texture and we need to create a texture mirror
  459.             if (m_dwTexMirrorWidth && m_dwTexMirrorHeight) 
  460.             {
  461.                 hr = AllocateTextureMirror(pStrmInfo->pddsVideoSurface, &m_dwTexMirrorWidth, &m_dwTexMirrorHeight,
  462.                     DoesSupportNonPow2CondCap(pd3dDevice));
  463.             }
  464.  
  465.             m_bInitCube = false;
  466.         }
  467.  
  468.         // Rotate the Cube
  469.         CHECK_HR(hr = FrameMove(pd3dDevice, ConvertToMilliseconds(rtStart) * 0.0005f));
  470.  
  471.         // Clear the viewport to dark gray
  472.         CHECK_HR(hr = pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0x00404040, 1.0f, 0L));
  473.  
  474.         cStreams = min(MAXSTREAMS, cStreams);
  475.  
  476.         StreamSize Sizes[MAXSTREAMS];
  477.         for (DWORD j = 0; j < MAXSTREAMS; j++)
  478.         {
  479.             int iStream = j % cStreams;
  480.  
  481.             if (m_StreamInfo[pStrmInfo[iStream].dwStrmID].bTexture) 
  482.             {
  483.                 Sizes[j].cx = (FLOAT)WIDTH(&m_StreamInfo[pStrmInfo[iStream].dwStrmID].SourceRect)  / (FLOAT)pStrmInfo[iStream].dwWidth;
  484.                 Sizes[j].cy = (FLOAT)HEIGHT(&m_StreamInfo[pStrmInfo[iStream].dwStrmID].SourceRect) / (FLOAT)pStrmInfo[iStream].dwHeight;
  485.             }
  486.             else 
  487.             {
  488.                 Sizes[j].cx = (FLOAT)WIDTH(&m_StreamInfo[pStrmInfo[iStream].dwStrmID].SourceRect)  / (FLOAT)m_dwTexMirrorWidth;
  489.                 Sizes[j].cy = (FLOAT)HEIGHT(&m_StreamInfo[pStrmInfo[iStream].dwStrmID].SourceRect) / (FLOAT)m_dwTexMirrorHeight;
  490.             }
  491.         }
  492.  
  493.         CreateCube(m_pCubeVertices, Sizes);
  494.  
  495.         // Begin the scene
  496.         CHECK_HR(hr = pd3dDevice->BeginScene());
  497.         bInScene = true;
  498.  
  499.         for (unsigned int i = 0; i < MAXSTREAMS; i++)
  500.         {
  501.             int iStream = i % cStreams;
  502.             //
  503.             // Make sure we are dealing with a texture surface - if not
  504.             // copy the stream to the mirror surface.
  505.             //
  506.             if (m_StreamInfo[pStrmInfo[iStream].dwStrmID].bTexture) 
  507.             {
  508.                 pDDS = pStrmInfo[iStream].pddsVideoSurface;
  509.             }
  510.             else 
  511.             {
  512.                 RECT r = { 0, 0, pStrmInfo->dwWidth, pStrmInfo->dwHeight };
  513.  
  514.                 pDDS = m_pDDSTextureMirror;
  515.                 CHECK_HR(hr = pDDS->Blt(&r, pStrmInfo[iStream].pddsVideoSurface, &r, DDBLT_WAIT, NULL));
  516.             }
  517.  
  518.             // Prepare the texture stages
  519.             CHECK_HR(hr = pd3dDevice->SetTexture(0, pDDS));
  520.             if (DoesSupportAnisoCap(pd3dDevice))
  521.             {
  522.                 CHECK_HR(hr = pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTFG_ANISOTROPIC));
  523.                 CHECK_HR(hr = pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTFN_ANISOTROPIC));
  524.                 CHECK_HR(hr = pd3dDevice->SetTextureStageState( 0, D3DTSS_MAXANISOTROPY, 4));
  525.             }
  526.             else if (DoesSupportLinearCap(pd3dDevice))
  527.             {
  528.                 CHECK_HR(hr = pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTFG_LINEAR));
  529.                 CHECK_HR(hr = pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTFN_LINEAR));
  530.             }
  531.             else
  532.             {
  533.                 CHECK_HR(hr = pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTFG_POINT));
  534.                 CHECK_HR(hr = pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTFN_POINT));
  535.             }
  536.             CHECK_HR(hr = pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP)); 
  537.  
  538.             // Draw the faces of the cube
  539.             CHECK_HR(hr = pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX,
  540.                                        m_pCubeVertices+(4*i), 4, NULL));
  541.             CHECK_HR(hr = pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX,
  542.                                        m_pCubeVertices+(4*i)+12, 4, NULL));
  543.         } // for i
  544.     }
  545.     __finally 
  546.     {
  547.         if (bInScene) {
  548.             // End the scene.
  549.             pd3dDevice->EndScene();
  550.         }
  551.     }
  552.     return S_OK;
  553. }
  554.  
  555. /*****************************Private*Routine******************************\
  556. * SetStreamMediaType
  557. *
  558. \**************************************************************************/
  559. HRESULT CMpegMovie::SetStreamMediaType(DWORD dwStrmID, AM_MEDIA_TYPE *pmt, BOOL fTexture)
  560. {
  561.     if (pmt)
  562.     {
  563.         m_StreamInfo[dwStrmID].bTexture = fTexture;
  564.         m_StreamInfo[dwStrmID].SourceRect = GetSourceRectFromMediaType(pmt);
  565.  
  566.         if (!fTexture) 
  567.         {
  568.             // choose the largest measure in each dimension
  569.             m_dwTexMirrorWidth = max(m_dwTexMirrorWidth, (DWORD)WIDTH(&m_StreamInfo[dwStrmID].SourceRect));
  570.             m_dwTexMirrorHeight = max(m_dwTexMirrorHeight, (DWORD)HEIGHT(&m_StreamInfo[dwStrmID].SourceRect));    
  571.         }
  572.     }
  573.     return S_OK;
  574. }
  575.  
  576. /*****************************Private*Routine******************************\
  577. * DoesSupportNonPow2CondCap
  578. *
  579. \**************************************************************************/
  580. bool CMpegMovie::DoesSupportNonPow2CondCap(LPDIRECT3DDEVICE7 pD3DDevice)
  581. {
  582.     ASSERT(pD3DDevice);
  583.     D3DDEVICEDESC7 ddDesc;
  584.     if (!(DD_OK == pD3DDevice->GetCaps(&ddDesc)))
  585.     {
  586.         return false;
  587.     }
  588.  
  589.     return (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) ? true : false;
  590. }
  591.  
  592. /*****************************Private*Routine******************************\
  593. * DoesSupportAnisoCap
  594. *
  595. \**************************************************************************/
  596. bool CMpegMovie::DoesSupportAnisoCap(LPDIRECT3DDEVICE7 pD3DDevice)
  597. {
  598.     ASSERT(pD3DDevice);
  599.     D3DDEVICEDESC7 ddDesc;
  600.     if (!(DD_OK == pD3DDevice->GetCaps(&ddDesc)))
  601.     {
  602.         return false;
  603.     }
  604.  
  605.     bool bMag = (ddDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) ? true : false;
  606.     bool bMin = (ddDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) ? true : false;
  607.     return (bMag && bMin);
  608. }
  609.  
  610. /*****************************Private*Routine******************************\
  611. * DoesSupportLinearCap
  612. *
  613. \**************************************************************************/
  614. bool CMpegMovie::DoesSupportLinearCap(LPDIRECT3DDEVICE7 pD3DDevice)
  615. {
  616.     ASSERT(pD3DDevice);
  617.     D3DDEVICEDESC7 ddDesc;
  618.     if (!(DD_OK == pD3DDevice->GetCaps(&ddDesc)))
  619.     {
  620.         return false;
  621.     }
  622.  
  623.     bool bMag = (ddDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR) ? true : false;
  624.     bool bMin = (ddDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR) ? true : false;
  625.     return (bMag && bMin);
  626. }